import { HttpClient, HttpRequest, provideHttpClient, withInterceptors } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';

import { httpAuthInterceptor } from './http-auth.interceptor';
import { Oauth2AuthService } from './oauth2-auth.service';

const URL = 'http://localhost:8080/api/dummy';
const HTTP_METHOD = 'GET';
const TOKEN = '1a2b3c';

const buildHttpRequest = () => {
  const originalRequest: HttpRequest<unknown> = new HttpRequest<unknown>(HTTP_METHOD, URL);
  return originalRequest.clone({
    headers: originalRequest.headers.append('ContentType', 'application/json'),
  });
};

describe('httpAuthInterceptor', () => {
  let httpTestingController: HttpTestingController;
  let httpClient: HttpClient;
  let oauth2AuthService: Oauth2AuthService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [provideHttpClient(withInterceptors([httpAuthInterceptor])), provideHttpClientTesting(), Oauth2AuthService],
    });
    httpTestingController = TestBed.inject(HttpTestingController);
    httpClient = TestBed.inject(HttpClient);
    oauth2AuthService = TestBed.inject(Oauth2AuthService);
  });

  describe('Bearer Token', () => {
    it('should add authorization bearer token in request when defined', () => {
      jest.spyOn(oauth2AuthService, 'token', 'get').mockReturnValue(TOKEN);
      const originalRequest = buildHttpRequest();

      httpClient.request(originalRequest).subscribe();

      const req = httpTestingController.expectOne(originalRequest.url);
      expect(req.request.method).toEqual(HTTP_METHOD);
      expect(req.request.url).toEqual(URL);
      expect(req.request.headers.get('ContentType')).toBe('application/json');
      expect(req.request.headers.get('Authorization')).toEqual(`Bearer ${TOKEN}`);
    });

    it('should not add authorization bearer token in request when it is not defined', () => {
      jest.spyOn(oauth2AuthService, 'token', 'get').mockReturnValue(undefined);
      const originalRequest: HttpRequest<unknown> = buildHttpRequest();

      httpClient.request(originalRequest).subscribe();

      const req = httpTestingController.expectOne(originalRequest.url);
      expect(req.request.headers.get('ContentType')).toBe('application/json');
      expect(req.request.headers.get('Authorization')).toBeFalsy();
    });
  });
});
